home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / WSKHOSTM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  15.2 KB  |  424 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.14  $
  6. //
  7. // Winsock for OWL subsystem.
  8. // Based on work by Paul Pedriana, 70541.3223@compuserve.com
  9. //----------------------------------------------------------------------------
  10. #include <owl/pch.h>
  11. #if !defined(OWL_WINSOCK_H)
  12. # include <owl/winsock.h>
  13. #endif
  14.  
  15. OWL_DIAGINFO;
  16.  
  17. //
  18. //
  19. //
  20. DEFINE_RESPONSE_TABLE1(THostInfoWindow, TWindow)
  21.    EV_MESSAGE(MSG_HOST_INFO_NOTIFY, DoNotification),
  22. END_RESPONSE_TABLE;
  23.  
  24. //
  25. // The HostInfoWindow requires a HostInfoManager, so it can
  26. // relay messages to it.
  27. //
  28. THostInfoWindow::THostInfoWindow(THostInfoManager* hostInfoManagerParent)
  29. :
  30.   TWindow(0, "HostInfo Window"),
  31.   HostInfoManagerParent(hostInfoManagerParent)
  32. {
  33.   Attr.Style = 0;  // Turn off WS_CHILD (the default) style).
  34. }
  35.  
  36. //
  37. // This is the relay function.
  38. //
  39. TResult THostInfoWindow::DoNotification(TParam1, TParam2 param2)
  40. {
  41.   HostInfoManagerParent->SetHostRequestCompleted(WSAGETASYNCERROR(param2));
  42.   return 1;
  43. }
  44.  
  45. //----------------------------------------------------------------------------
  46.  
  47. //
  48. // Constructor of THostEntry object. Initialize members describing host to 0.
  49. //
  50. THostEntry::THostEntry()
  51. {
  52.   h_name      = 0;
  53.   h_aliases   = 0;
  54.   h_addrtype  = 0;
  55.   h_length    = 0;
  56.   h_addr_list = 0;
  57. }
  58.  
  59. //
  60. // Returns the number of pointers to addresses in the hostent (parent
  61. // class of THostEntry).
  62. //
  63. int THostEntry::GetAddressCount()
  64. {
  65.   int i = 0;
  66.   while (h_addr_list[i])
  67.     i++;
  68.  
  69.   return i;
  70. }
  71.  
  72. //
  73. // This function is FLAWED in that it is internet addressing-specific
  74. //  (AF_INET/PF_INET).
  75. // The proper way to implement this function would be to look at h_addrtype
  76. //  and h_length to determine the nature of the address type and return
  77. //  something useful or make a derived class that knows about each address
  78. //  family. (...)
  79. //
  80. ulong THostEntry::GetNthINetAddress(int index)
  81. {
  82.   int addressCount = GetAddressCount();
  83.  
  84.   if (index >= addressCount)
  85.     return 0;  //The caller asked for an address index that is out of range.
  86.  
  87.   return *((ulong*)h_addr_list[index]);
  88. }
  89.  
  90. //----------------------------------------------------------------------------
  91. // THostInfoManager
  92. //
  93.  
  94. //
  95. // Initialize the hidden window.
  96. //
  97. THostInfoManager::THostInfoManager()
  98. :
  99.   HostWindow(this)
  100. {
  101.   HostEntry            = (THostEntry*)&HostInfoBuffer;
  102.   HostRequest          = 0;
  103.   LastError            = 0;
  104.   HostRequestCompleted = false;
  105.   try {
  106.     HostWindow.Create();
  107.   }
  108.   catch (...) {
  109.     //::MessageBeep(10);  
  110.  }
  111. }
  112.  
  113. //
  114. // In this destructor, we need to clear any pending requests before we
  115. // get deleted.
  116. //
  117. THostInfoManager::~THostInfoManager()
  118. {
  119.   if (HostRequest && !HostRequestCompleted) // If there is an outstanding request...
  120.     CancelHostRequest();
  121. }
  122.  
  123. //
  124. // This function returns the name of the computer on which this program is running. The
  125. //  szName paramter will be set to be the name.
  126. // The return value is either WINSOCK_ERROR or WINSOCK_NOERROR.  You can call the
  127. //  THostInfoManager's GetLastError() to get the actual error value.
  128. // name is a pointer to pre-allocated buffer of minimum size of nNameLength
  129. // nameLength should be at least N_MAX_HOST_NAME.
  130. //
  131. int THostInfoManager::GetHostName(char far* name, int nameLength)
  132. {
  133.   if (TWinSockDll::gethostname(name, nameLength) == SOCKET_ERROR) {
  134.     LastError = TWinSockDll::WSAGetLastError();
  135.     return WINSOCK_ERROR;
  136.   }
  137.   return WINSOCK_NOERROR;
  138. }
  139.  
  140. //
  141. // This function effectively converts szHostName to szHostAddress.  If you have a
  142. //  name such as "joe_schmoe@borland.com", and you want the dotted-decimal IP
  143. //  address for it, you would call this function.
  144. // This function assumes that you have enough space in szHostAddress for the address.
  145. // This function, like most of Winsock 1.1, currently works with only IP addresses.
  146. //  Thus, the szHostAddress is always going to be dotted-decimal format in Winsock 1.1.
  147. // Note that while the inet_ntoa() function has the limitation (feature) that the
  148. //  char* string returned resides in Winsock memory space, the szHostAddress returned
  149. //  is allocated and owned by the caller of this function and can be manipulated any way
  150. //  the caller wants.
  151. // This function returns an error value of WINSOCK_ERROR or WINSOCK_NOERROR.
  152. //
  153. int THostInfoManager::GetHostAddress(char far* hostAddress, const char far* hostName)
  154. {
  155.   THostEntry* tempHostEntry;
  156.  
  157.   int error = GetHostInfo(tempHostEntry, hostName);
  158.   if (error == WINSOCK_ERROR)
  159.      return error;
  160.   return HostEntryToAddress(tempHostEntry, hostAddress);
  161. }
  162.  
  163. //
  164. // This function effectively converts szHostName to a SocketAddres.  If you have
  165. //  a name such as "joe_schmoe@borland.com", and you want the TSocketAddress for
  166. //  it, you could call this function.
  167. // This function, like most of Winsock 1.1, currently works with only IP addresses.
  168. //  Thus, the szHostAddress is always going to be dotted-decimal format in Winsock 1.1.
  169. // This function returns an error value of WINSOCK_ERROR or WINSOCK_NOERROR.
  170. //
  171. int THostInfoManager::GetHostAddress(TSocketAddress& address, const char far* hostName)
  172. {
  173.    THostEntry* tempHostEntry;
  174.  
  175.    int error = GetHostInfo(tempHostEntry, hostName);
  176.    if (error == WINSOCK_ERROR)
  177.       return error;
  178.    return HostEntryToAddress(tempHostEntry, address);
  179. }
  180.  
  181. //
  182. // The caller of this function is supplying a pointer to be assigned by this function.  Note
  183. //  that the caller need not allocate space for any THostEntry structure.  Note also that
  184. //  because of this, the data needs to be read immediately or copied for later use.
  185. //
  186. // address is a preallocated SocketAddress reference.  Due to the design of the socket api, the
  187. //  call to gethostbyaddr currently requires a pointer to the internet address, rather than
  188. //  a sockaddr or even a sockaddr_in.  Because passing a ulong pointer would most likely
  189. //  not work if the socket api was to support something other than IP, we fix this issue by
  190. //  making a sockaddr interface to this api.  This comment applies to some other functions
  191. //  in this class as well.
  192. //
  193. // The address is in network byte ordering.  Note that the call below requires the address in
  194. //  network byte ordering.
  195. //
  196. int THostInfoManager::GetHostInfo(THostEntry*& entry, const TSocketAddress& address)
  197. {
  198.   sockaddr_in* tempSockAddrIn = (sockaddr_in*)&address;
  199.   tempSockAddrIn->sin_addr.s_addr = tempSockAddrIn->sin_addr.s_addr;
  200.  
  201.   entry = (THostEntry*)TWinSockDll::gethostbyaddr(
  202.                                    (const char far*)&tempSockAddrIn->sin_addr.s_addr,
  203.                                    sizeof(ulong), PF_INET);
  204.   if (!entry) {
  205.     LastError = TWinSockDll::WSAGetLastError();
  206.     return WINSOCK_ERROR;
  207.   }
  208.   return WINSOCK_NOERROR;
  209. }
  210.  
  211. //
  212. // This call is potentially blocking.
  213. //
  214. // entry is a pointer passed by reference.  The system will change that pointer to
  215. //  point to an internal winsock data structure.  You must NOT modify its contents.
  216. //
  217. // name is a pre-allocated string that holds a string.  Holds address in text format.
  218. //
  219. // The caller of this function passes a pointer to a THostEntry struct. e.g.:
  220. //   THostEntry* tempTHostEntry;
  221. //   GetHostInfo(tempTHostEntry, "JoeShmoe@anywhere.com");
  222. //   printf("%s", tempTHostEntry->h_name);  //h_name should be "joeSchmoe@anywhere,com"
  223. //
  224. int THostInfoManager::GetHostInfo(THostEntry*& entry, const char far* name)
  225. {
  226.   entry = (THostEntry*)TWinSockDll::gethostbyname(name);
  227.   if (!entry) {
  228.     LastError = TWinSockDll::WSAGetLastError();
  229.     return WINSOCK_ERROR;
  230.   }
  231.   return WINSOCK_NOERROR;
  232. }
  233.  
  234. //
  235. // The caller can cancel the last pending request with this call.
  236. //
  237. int THostInfoManager::CancelHostRequest(HANDLE hostRequest)
  238. {
  239.   if (!hostRequest)
  240.     hostRequest = HostRequest;
  241.  
  242.   if (!hostRequest) {
  243.     LastError = WSAEINVAL;  // There is no handle to use.
  244.     return WINSOCK_ERROR;
  245.   }
  246.  
  247.   if (TWinSockDll::WSACancelAsyncRequest(hostRequest) == SOCKET_ERROR) {
  248.     LastError = TWinSockDll::WSAGetLastError();
  249.     return WINSOCK_ERROR;
  250.   }
  251.  
  252.   return WINSOCK_NOERROR;
  253. }
  254.  
  255. //
  256. // The 'theHostRequest' parameter will be returned to the caller with the
  257. //  asynchrous request handle.
  258. // 'address' needs to be in network byte ordering.
  259. //
  260. // Note that due to the design of this class, you cannot have two outstanding
  261. //  Service requests that get notified directly to this class.  You may use the
  262. //  hwnd-specific notification version of this function to manage multiple
  263. //  requests at a time.
  264. //  You may also simply create more than one instance of this class.
  265. //
  266. // The service is complete when HostRequestCompleted is true.  You must look at
  267. //  LastError in this case to see if there was an error. Note also that you must
  268. //  not issue any async calls that post to this class' hwnd until the previous
  269. //  request is completed.
  270. //  The alternative is simply to create multiple THostInfoManagers, or manage
  271. //  the call-backs yourself.
  272. //
  273. // For info about the nasty casting done below, see the comments about the
  274. //  non-Async version of this call.
  275. //
  276. int THostInfoManager::GetHostInfoAsync(HANDLE& hostRequest, TSocketAddress& address)
  277. {
  278.   sockaddr_in* tempSockAddrIn = (sockaddr_in*)&address;
  279.   tempSockAddrIn->sin_addr.s_addr = tempSockAddrIn->sin_addr.s_addr;
  280.  
  281.   HostRequestCompleted = false;
  282.   HostRequest = hostRequest =
  283.     TWinSockDll::WSAAsyncGetHostByAddr(HostWindow, MSG_HOST_INFO_NOTIFY,
  284.                                     (char far*)&tempSockAddrIn->sin_addr.s_addr,
  285.                                     sizeof(ulong), PF_INET, HostInfoBuffer,
  286.                                     MAXGETHOSTSTRUCT);
  287.   if (!hostRequest) {
  288.     LastError = TWinSockDll::WSAGetLastError();
  289.     return WINSOCK_ERROR;
  290.   }
  291.   return WINSOCK_NOERROR;
  292. }
  293.  
  294. //
  295. // Return same information as other version of GetHostInfoAsync.
  296. // The difference is the host name can be a string, rather than a TSocketAddress.
  297. //
  298. int THostInfoManager::GetHostInfoAsync(HANDLE& theHostRequest, char far* name)
  299. {
  300.   HostRequestCompleted = false;
  301.   HostRequest = theHostRequest =
  302.       TWinSockDll::WSAAsyncGetHostByName(HostWindow, MSG_HOST_INFO_NOTIFY, name,
  303.                                       HostInfoBuffer, MAXGETHOSTSTRUCT);
  304.  
  305.   if (!HostRequest) {
  306.     LastError = TWinSockDll::WSAGetLastError();
  307.     return WINSOCK_ERROR;
  308.   }
  309.   return WINSOCK_NOERROR;
  310. }
  311.  
  312. //
  313. // This function notifies the given window about the completion of the request.
  314. // nMessage is the message that the hwndNotify will receive. It defaults to MSG_HOST_INFO_NOTIFY,
  315. //  which is defined in the THostInfoManager's header file.
  316. // The chBuffer is a pointer to buffer that will be filled in with a hostent.  Needs to be at least
  317. //  MAXGETHOSTSTRUCT bytes.  If chBuffer is 0 (or not specified), then the THostInfoManager's
  318. //  internal buffer will be used.
  319. // The hTheHostRequest will hold a handle that the caller can use to reference the request on call-back.
  320. //   wParam will be equal to the hService returned.
  321. //   WSAGETSYNCERROR(lParam)   holds an error, if any (0 is OK).
  322. //   WSAGETSYNCBUFLEN(lParam)  hold actual length of buffer
  323. // When this function returns, myTHostEntry will be filled in with the appropriate information.
  324. //  Since this information belongs to this object, you can delay reading it as long as you wish.
  325. // Note that while the sAddress should be passed in network byte ordering, the output on callback
  326. //  will also be in network ordering.
  327. //
  328. int THostInfoManager::GetHostInfoAsync(TWindow& wndNotify, HANDLE& hostRequest,
  329.                                        TSocketAddress& address, uint message,
  330.                                        char far* buffer)
  331. {
  332.   sockaddr_in* tempSockAddrIn = (sockaddr_in*)&address;
  333.   tempSockAddrIn->sin_addr.s_addr = tempSockAddrIn->sin_addr.s_addr;
  334.  
  335.   char far* bufferToUse = buffer ? buffer : HostInfoBuffer;
  336.  
  337.   HostRequestCompleted = false;
  338.   HostRequest = hostRequest =
  339.     TWinSockDll::WSAAsyncGetHostByAddr(wndNotify, message,
  340.                                     (char far*)&tempSockAddrIn->sin_addr.s_addr,
  341.                                     sizeof(ulong), PF_INET, bufferToUse,
  342.                                     MAXGETHOSTSTRUCT);
  343.  
  344.   if (!hostRequest) {
  345.     LastError = TWinSockDll::WSAGetLastError();
  346.     return WINSOCK_ERROR;
  347.   }
  348.   return WINSOCK_NOERROR;
  349. }
  350.  
  351. //
  352. // hwndNotify is the window that will get the message that the request has completed.
  353. // nMessage is the message that the hwndNotify will receive. It defaults to MSG_HOST_INFO_NOTIFY,
  354. //  which is defined in the THostInfoManager's header file.
  355. // hTheHostRequest is the asynchrous request handle that will be a reference to the request.
  356. // szName is the name of the host, as in "coyote@acme.com"
  357. // The chBuffer is a pointer to buffer that will be filled in with a hostent.  Needs to be at least
  358. //  MAXGETHOSTSTRUCT bytes.  If chBuffer is 0 (or not specified), then the THostInfoManager's
  359. //  internal buffer will be used.
  360. // The returned address will be in network byte ordering.
  361. //
  362. int THostInfoManager::GetHostInfoAsync(TWindow& wndNotify, HANDLE& hostRequest, char far* name,
  363.                                        uint message, char far* buffer)
  364. {
  365.   char far* bufferToUse = buffer ? buffer : HostInfoBuffer;
  366.  
  367.   HostRequestCompleted = false;
  368.   HostRequest = hostRequest =
  369.      TWinSockDll::WSAAsyncGetHostByName(wndNotify, message, name, bufferToUse,
  370.                                      MAXGETHOSTSTRUCT);
  371.  
  372.   if (!hostRequest) {
  373.     LastError = TWinSockDll::WSAGetLastError();
  374.     return WINSOCK_ERROR;
  375.   }
  376.   return WINSOCK_NOERROR;
  377. }
  378.  
  379. //
  380. // Given a THostEntry*, this function converts it to a dotted-decimal szAddress.
  381. // Since Winsock 1.1 supports only IP addressing, this function is limited to
  382. //  IP addressing and the address will always be only dotted-decimal.
  383. //
  384. // The return value is WINSOCK_ERROR or WINSOCK_NOERROR.
  385. //
  386. int THostInfoManager::HostEntryToAddress(THostEntry* entry, char far* address)
  387. {
  388.   in_addr    tempInAddr;
  389.   tempInAddr.s_addr = *((ulong*)entry->h_addr);
  390.             //else: = *((ulong*)hEntry->h_addr_list[0])
  391.  
  392.   char far* tempAddress = TWinSockDll::inet_ntoa(tempInAddr);
  393.   if (!tempAddress)
  394.     return WINSOCK_ERROR;
  395.   strcpy(address, tempAddress);
  396.   return WINSOCK_NOERROR;
  397. }
  398.  
  399. //
  400. // Given a THostEntry*, this function converts it to a SocketAddress. Since
  401. //  Winsock 1.1 supports only IP addressing, this function is limited to IP
  402. //  addressing and the address will be an INetSocketAddress.
  403. // The return value is WINSOCK_ERROR or WINSOCK_NOERROR.
  404. //
  405. int THostInfoManager::HostEntryToAddress(THostEntry* entry, TSocketAddress& address)
  406. {
  407.   TINetSocketAddress *addr = STATIC_CAST(TINetSocketAddress*, &address);
  408.   addr->SetNetworkAddress(*((ulong*)entry->h_addr));
  409.   return WINSOCK_NOERROR;
  410. }
  411.  
  412. //
  413. // This function is called whenever an async request is completed.
  414. // You may want to subclass this function.  If you do, you will probably want to call this
  415. //  function as part of the subclassed function.
  416. //
  417. void THostInfoManager::SetHostRequestCompleted(int result)
  418. {
  419.   int error = WSAGETASYNCERROR(result);
  420.   if (error != 0)
  421.     LastError = error;
  422.   HostRequestCompleted = true;  // Of course, there may have been an error.
  423. }
  424.